'''
Created on Jan 12, 2011

@author: Jonathan Herbst
'''

import time

class Message():
    
    _messageType = ""
    _messageContext = ""
    
    def __init__(self):
        self.m_varList = []
        
    def renderMessage(self):
        message = "%s:%s" % (self._messageType, self._messageContext)
        for var in self.m_varList:
            message += "," + str(var)
        return message + ";"
    
        
class Alert(Message): _messageType = "alert"
class Command(Message): _messageType = "command"
class Configuration(Message): _messageType = "config"


class EntrantDetected(Alert):
    
    _messageContext = "entrantDetected"
    
    def __init__(self, *args):
        if len(args) == 4:
            args = args[1:]
        elif len(args) != 3:
            raise AttributeError()
        self.m_cameraIPAddress = str(args[0])
        self.m_cameraAccessPort = int(args[1])
        self.m_queueName = str(args[2])
        
    def renderMessage(self):
        self.m_varList = [int(time.time()), self.m_cameraIPAddress, self.m_cameraAccessPort, self.m_queueName]
        return Alert.renderMessage(self)
    
    
class EntrantDetectedLAN(Alert):
    
    _messageContext = "entrantDetectedLAN"
    
    def __init__(self, *args):
        if len(args) > 1:
            raise AttributeError()
        
    def renderMessage(self):
        self.m_varList = [int(time.time())]
        return Alert.renderMessage(self)
    
        
class AlertCanceled(Alert):
    
    _messageContext = "canceled"
    
    def __init__(self, reason):
        self.m_reason = reason
        
    def renderMessage(self):
        self.m_varList = [self.m_reason]
        return Alert.renderMessage(self)
    
class CommandReceived(AlertCanceled): _messageContext = "commandReceived"
    
    
class InvalidKey(Alert): _messageContext = "invalidKey"
    

class DoorCommand(Command):
    
    GRANTACCESSACTION = "grantAccess"
    DENYACCESSACTION = "denyAccess"
    
    _messageContext = "door"
    
    def __init__(self, key, action):
        self.key = str(key)
        self.action = str(action)
        
    def renderMessage(self):
        self.m_varList = [self.key, self.action]
        return Command.renderMessage(self)
    
class BTDoorCommand(DoorCommand):
    
    def __init__(self, doorCommand):
        DoorCommand.__init__(self, doorCommand.key, doorCommand.action)
        
class PCAppDoorCommand(DoorCommand):
    
    def __init__(self, doorCommand):
        DoorCommand.__init__(self, doorCommand.key, doorCommand.action)
        
class SQSDoorCommand(DoorCommand):
    
    def __init__(self, doorCommand):
        DoorCommand.__init__(self, doorCommand.key, doorCommand.action)
    
class PBDoorCommand(PCAppDoorCommand):
    
    def __init__(self, action):
        DoorCommand.__init__(self, "", action)
        
    
class C2DMRegistration(Command):
    
    _messageContext = "c2DMRegistration"
    
    def __init__(self, registrationId):
        self.m_registrationId = registrationId
        
    def RegistrationId(self):
        return self.m_registrationId
        
    def renderMessage(self):
        self.m_varList = [self.m_registrationId]
        return Command.renderMessage(self)
        

class KeyGenerate(Configuration):
    
    _messageContext = "regenerateKey"
    
    def __init__(self, key):
        self.m_key = key
        
    def renderMessage(self):
        self.m_varList = [self.m_key]
        return Configuration.renderMessage(self)
    

class KeyGenerateResponse(Configuration):
    
    _messageContext = "newKey"
    
    def __init__(self, newKey):
        self.m_newKey = newKey
        
    def renderMessage(self):
        self.m_varList = [self.m_newKey]
        return Configuration.renderMessage(self)
    

class PCAppLogin(Configuration):
    
    _messageContext = "login"
    
    def __init__(self, userName, password):
        self.userName = userName
        self.password = password
        
    def renderMessage(self):
        self.m_varList = [self.userName, self.password]
        return Configuration.renderMessage(self)
    
class PCAppLoginFailed(Configuration): _messageContext = "loginFailed"

class PCAppLoginSuccess(Configuration):
    
    _messageContext = "loginSuccess"
    
    def __init__(self, key):
        self.key = key
        
    def renderMessage(self):
        self.m_varList = [self.key]
        return Configuration.renderMessage(self)

class SetUserName(Configuration):
    
    _messageContext = "userName"
    
    def __init__(self, key, newUserName):
        self.key = key
        self.newUserName = newUserName
        
    def renderMessage(self):
        self.m_varList = [self.key, self.newUserName]
        return Configuration.renderMessage(self)
    
class SetPassword(Configuration):
    
    _messageContext = "password"
    
    def __init__(self, key, newPassword):
        self.key = key
        self.newPassword = newPassword
        
    def renderMessage(self):
        self.m_varList = [self.key, self.newPassword]
        return Configuration.renderMessage(self)
    
SIGNIATURE_TO_CLASS = {"alert:entrantDetected": EntrantDetected,
                       "alert:canceled": AlertCanceled,
                       "alert:invalidKey": InvalidKey,
                       "command:door": DoorCommand,
                       "command:c2DMRegistration": C2DMRegistration,
                       "config:regenerateKey": KeyGenerate,
                       "config:newKey": KeyGenerateResponse,
                       "config:login": PCAppLogin,
                       #"config:loginFailed": PCAppLoginFailed,
                       #"config:loginSuccess": PCAppLoginSuccess,
                       "config:userName": SetUserName,
                       "config:password": SetPassword,
                       }

def parseMessage(message):
    
    message = str(message)
    message = message.strip()
    
    if message[-1] is not ";":
        print "NO SEMICOLON"
        return None
    
    message = message[0:-1]
    messageList = message.split(",")
    
    if len(messageList) < 1:
        print "NO MESSAGE"
        return None
    if messageList[0] not in SIGNIATURE_TO_CLASS:
        print messageList[0] + ": INVALID SIGNIATURE"
        return None
    
    messageClass = SIGNIATURE_TO_CLASS[messageList[0]]
    try:
        message = messageClass(*messageList[1:])
    except:
        print "UNABLE TO CONSTRUCT CLASS"
        return None
    
    return message

ACCEPTABLE_FROM_BLUETOOTH = [DoorCommand, KeyGenerate]
    
    
def testMessageClass(messageClass, *args):
    message = messageClass(*args)
    message = message.renderMessage()
    print message
    message = parseMessage(message)
    print message.renderMessage()
    
if __name__ == "__main__":
    testMessageClass(EntrantDetected, "192.168.0.1", "8000", "SECS")
    print
    testMessageClass(AlertCanceled, "timeout")
    print
    testMessageClass(InvalidKey)
    print
    testMessageClass(DoorCommand, "1bd6f1f0cf321afee3350cebdc272ce2b47faf0bfbcdd6b3fa276566fae4d120", "grantAccess")
    print
    testMessageClass(KeyGenerate, "1bd6f1f0cf321afee3350cebdc272ce2b47faf0bfbcdd6b3fa276566fae4d120")
    print
    testMessageClass(KeyGenerateResponse, "1bd6f1f0cf321afee3350cebdc272ce2b47faf0bfbcdd6b3fa276566fae4d120")
    
    